package com.seleniti.enpareja.web.desktop.client.ui.view;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.ioc.commons.extra.gwt.extensions.cell.client.ClickableHtmlCell;
import org.ioc.commons.extra.gwt.extensions.cellview.client.CheckColumn;
import org.ioc.commons.extra.gwt.extensions.cellview.client.ModifiableSafeHtmlHeader;
import org.ioc.commons.impl.gwt.client.ui.HasEnabledWrapper;
import org.ioc.commons.impl.gwt.client.ui.HasValueWrapper;
import org.ioc.commons.impl.gwt.client.ui.ViewComposite;
import org.ioc.commons.impl.gwt.shared.common.util.WrappedDeckPanelAsEnum;
import org.ioc.commons.ui.HasEnabled;
import org.ioc.commons.ui.HasValue;
import org.ioc.commons.ui.HasVisibility;
import org.ioc.commons.ui.impl.HasValueAdapter;
import org.ioc.commons.ui.impl.HasVisibilityAdapter;
import org.ioc.commons.ui.impl.OnChangeCommand;
import org.ioc.commons.utils.FormatterLogger;

import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.cell.client.NumberCell;
import com.google.gwt.cell.client.SafeHtmlCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.builder.shared.HtmlBuilderFactory;
import com.google.gwt.dom.builder.shared.HtmlDivBuilder;
import com.google.gwt.dom.client.ButtonElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.client.SafeHtmlTemplates.Template;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.cellview.client.RowStyles;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.DeckLayoutPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Html5BigDecimalBox;
import com.google.gwt.user.client.ui.Html5DateBox;
import com.google.gwt.user.client.ui.Html5FormPanel;
import com.google.gwt.user.client.ui.Html5TextBox;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
import com.google.gwt.view.client.SetSelectionModel;
import com.google.gwt.view.client.SingleSelectionModel;
import com.seleniti.enpareja.controller.model.integration.database.domain.SharedExpense;
import com.seleniti.enpareja.controller.model.integration.database.domain.SharedExpense.MadeBy;
import com.seleniti.enpareja.controller.ui.view.SharedExpensesView;
import com.seleniti.enpareja.controller.ui.view.SharedExpensesView.Action;
import com.seleniti.enpareja.controller.ui.view.SharedExpensesView.Event;
import com.seleniti.enpareja.controller.ui.view.SharedExpensesView.Operation;
import com.seleniti.enpareja.controller.ui.view.SharedExpensesView.Presenter;
import com.seleniti.enpareja.controller.ui.view.SharedExpensesViewPresenter;
import com.seleniti.enpareja.web.desktop.client.ui.cell.EnParejaTemplate;
import com.seleniti.enpareja.web.desktop.client.ui.resources.CommonResources;
import com.seleniti.enpareja.web.desktop.client.ui.widget.InfoInlineWidget;

public class SharedExpensesViewWidget extends EnParejaBaseView<Event, Operation, Action, Presenter> implements
		SharedExpensesView {

	private static final FormatterLogger logger = FormatterLogger.getLogger(SharedExpensesViewWidget.class);

	private static TemplateUiBinder uiBinder = GWT.create(TemplateUiBinder.class);

	static interface Template extends SafeHtmlTemplates {
		@Template("<div><span class='{0}'>{1}</span> debe <span class='{2}'>{3}</span> a <span class='{4}'>{5}</span></div>")
		SafeHtml owes(String member1ClassName, String member1Name, String amountClassName, String amount,
				String member2ClassName, String member2Name);
	}

	private static Template sharedExpensesTemplate;

	private class SharedExpensesHeader extends ModifiableSafeHtmlHeader {
		private final MadeBy madeBy;

		private SharedExpensesHeader(SafeHtml text, MadeBy madeBy) {
			super(text, new ClickableHtmlCell());
			this.madeBy = madeBy;
		}

		@Override
		public void onBrowserEvent(Context context, Element elem, NativeEvent nativeEvent) {
			int eventType = com.google.gwt.user.client.Event.as(nativeEvent).getTypeInt();

			Element button = null;
			if (eventType == com.google.gwt.user.client.Event.ONCLICK) {
				for (button = nativeEvent.getEventTarget().cast(); button != null
						&& !button.getTagName().equalsIgnoreCase(ButtonElement.TAG); button = button.getParentElement())
					;
			}

			if (button != null) {
				nativeEvent.preventDefault();
				addSharedExpense(madeBy);
			} else {
				super.onBrowserEvent(context, elem, nativeEvent);
			}

		}
	}

	interface TemplateUiBinder extends UiBinder<Widget, SharedExpensesViewWidget> {
	}

	public static interface Style extends CssResource {
		String container();

		String selector();

		String dialog();

		String label();

		String date();

		String description();

		String amount();

		String nonShared();
	}

	@UiField(provided = true)
	DataGrid<SharedExpense> lstElements;

	@UiField
	Style style;

	@UiField
	ToggleButton btnDelete;

	@UiField
	CommonResources common;

	@UiField
	VerticalPanel doneSettingsPanel;

	@UiField
	DeckLayoutPanel mainPanel;

	@UiField
	Label formMember;

	@UiField
	Html5DateBox date;

	@UiField
	Html5TextBox description;

	@UiField(provided = true)
	Html5BigDecimalBox amount;

	@UiField(provided = true)
	Html5BigDecimalBox totalMember1;

	@UiField(provided = true)
	Html5BigDecimalBox totalMember2;

	@UiField
	Html5FormPanel form;

	@UiField
	HTML result;

	@UiField
	CheckBox shared;

	@UiField
	InfoInlineWidget nonSharedInfo;

	@UiField
	SimplePanel pnlTotalMember1;

	@UiField
	SimplePanel pnlTotalMember2;

	private ListDataProvider<SharedExpense> listDataProvider;

	private boolean loading;

	private ProvidesKey<SharedExpense> keyProvider;

	private ActionMode actionMode;

	private boolean enabled = true;

	private SingleSelectionModel<SharedExpense> singleSelectionModel;

	private ModifiableSafeHtmlHeader member1Header;

	private ModifiableSafeHtmlHeader member2Header;

	private boolean pendingHeaderRedraw;

	private SharedExpense modifyingElement;

	private CheckColumn<SharedExpense> checkColumn;

	private WrappedDeckPanelAsEnum<Board> boardManager;

	private MultiSelectionModel<SharedExpense> multiSelectionModel;

	private static EnParejaTemplate template;

	public SharedExpensesViewWidget() {

		if (template == null) {
			template = GWT.create(EnParejaTemplate.class);
		}

		if (sharedExpensesTemplate == null) {
			sharedExpensesTemplate = GWT.create(Template.class);
		}

		this.presenter = new SharedExpensesViewPresenter(this, eventbus, operationManager, actionController);

		this.keyProvider = new ProvidesKey<SharedExpense>() {

			@Override
			public Object getKey(SharedExpense item) {
				return item != null ? item.getSharedExpenseId() : null;
			}
		};

		this.amount = new Html5BigDecimalBox() {
			@Override
			public void setValue(BigDecimal value) {
				if (value != null) {
					value = value.setScale(2, RoundingMode.HALF_UP);
				}
				super.setValue(value);
			}
		};

		this.totalMember1 = new Html5BigDecimalBox() {
			@Override
			public void setValue(BigDecimal value) {
				if (value != null) {
					value = value.setScale(2, RoundingMode.HALF_UP);
				}
				super.setValue(value);
			}
		};

		this.totalMember2 = new Html5BigDecimalBox() {
			@Override
			public void setValue(BigDecimal value) {
				if (value != null) {
					value = value.setScale(2, RoundingMode.HALF_UP);
				}
				super.setValue(value);
			}
		};

		this.lstElements = new DataGrid<SharedExpense>(Integer.MAX_VALUE, keyProvider);

		this.lstElements.setRowStyles(new RowStyles<SharedExpense>() {

			@Override
			public String getStyleNames(SharedExpense row, int rowIndex) {
				StringBuffer styleNames = new StringBuffer();

				styleNames.append(common.style().commonText()).append(' ');

				if (row != null) {
					switch (row.getMadeBy()) {
					case MEMBER_1:
						styleNames.append(common.style().member1());
						break;
					case MEMBER_2:
						styleNames.append(common.style().member2());
						break;
					}

					// if (!row.isShared()) {
					// styleNames.append(' ').append(style.nonShared());
					// }
				}

				return styleNames.toString();
			}
		});

		HTML empty = new HTML("Ningún elemento en tu lista");
		this.lstElements.setEmptyTableWidget(empty);

		this.singleSelectionModel = new SingleSelectionModel<SharedExpense>(keyProvider);

		this.singleSelectionModel.addSelectionChangeHandler(new Handler() {

			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				presenter.onSelectionChanged();
			}
		});

		this.multiSelectionModel = new MultiSelectionModel<SharedExpense>(keyProvider);

		this.multiSelectionModel.addSelectionChangeHandler(new Handler() {

			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				presenter.onSelectionChanged();
			}
		});

		initWidget(uiBinder.createAndBindUi(this));

		initColumns();

		this.listDataProvider = new ListDataProvider<SharedExpense>();
		this.listDataProvider.addDataDisplay(lstElements);

		empty.setStyleName(common.style().emptyList());

		this.boardManager = new WrappedDeckPanelAsEnum<Board>(mainPanel, Board.values());
		this.boardManager.setValue(Board.MAIN_LIST);

		this.lstElements.getElement().getParentElement().getStyle().setOverflow(Overflow.VISIBLE);

	}

	protected void initColumns() {
		for (int i = this.lstElements.getColumnCount() - 1; i >= 0; i--) {
			this.lstElements.removeColumn(i);
		}

		Column<SharedExpense, SafeHtml> dateDescColumn = new Column<SharedExpense, SafeHtml>(new SafeHtmlCell()) {

			@Override
			public SafeHtml getValue(SharedExpense object) {
				HtmlDivBuilder builder = HtmlBuilderFactory.get().createDivBuilder();
				if (object != null) {
					builder.startDiv().className(style.description())
							.text(object.getText() != null ? object.getText() : "").endDiv();
					if (object.getDate() != null) {
						builder.startSpan().className(style.date())
								.text(DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT).format(object.getDate()))
								.endSpan();
						builder.startBR().end();
					}
				}

				return builder.asSafeHtml();
			}

			@Override
			public String getCellStyleNames(Context context, SharedExpense object) {
				String cellStyleNames = super.getCellStyleNames(context, object);

				if (!object.isShared()) {
					cellStyleNames += " " + style.nonShared();
				}

				return cellStyleNames;
			}
		};

		Column<SharedExpense, Number> member1Column = new Column<SharedExpense, Number>(new NumberCell()) {

			@Override
			public Number getValue(SharedExpense object) {
				return object != null && object.getMadeBy() == MadeBy.MEMBER_1 ? object.getAmount() : null;
			}
		};

		Column<SharedExpense, Number> member2Column = new Column<SharedExpense, Number>(new NumberCell()) {

			@Override
			public Number getValue(SharedExpense object) {
				return object != null && object.getMadeBy() == MadeBy.MEMBER_2 ? object.getAmount() : null;
			}
		};

		this.lstElements.addColumn(dateDescColumn, ""/* , "Fecha" */);

		this.lstElements.setColumnWidth(dateDescColumn, "40%");

		this.member1Header = new SharedExpensesHeader(getMemberHeaderSafeHtml("", null), MadeBy.MEMBER_1);
		this.member2Header = new SharedExpensesHeader(getMemberHeaderSafeHtml("", null), MadeBy.MEMBER_2);

		boolean single = false;
		if (member1ActionsVisible().isVisible()) {
			this.lstElements.addColumn(member1Column, member1Header);
		} else {
			single = true;
		}

		if (member2ActionsVisible().isVisible()) {
			this.lstElements.addColumn(member2Column, member2Header);
		} else {
			single = true;
		}

		if (!single) {
			member1Column.setCellStyleNames(style.label() + " " + common.style().member1());
			member2Column.setCellStyleNames(style.label() + " " + common.style().member2());
		} else {
			member1Column.setCellStyleNames(style.label() + " " + common.style().single());
			member2Column.setCellStyleNames(style.label() + " " + common.style().single());
		}

		this.lstElements.getHeader(0).setHeaderStyleNames(/*
														 * common.style().
														 * columnHeader() + " "
														 * +
														 */style.date() + " " + style.description());
		if (!single) {
			this.member1Header.setHeaderStyleNames(common.style().columnHeader() + " " + common.style().member1());
			this.member2Header.setHeaderStyleNames(common.style().columnHeader() + " " + common.style().member2());
		} else {
			this.member1Header.setHeaderStyleNames(common.style().columnHeader() + " " + common.style().single());
			this.member2Header.setHeaderStyleNames(common.style().columnHeader() + " " + common.style().single());
		}

	}

	@Override
	public void addSharedExpense(MadeBy madeBy) {
		this.presenter.onAddSharedExpense(madeBy);
	}

	private SafeHtml getMemberHeaderSafeHtml(String memberName, MadeBy member) {
		return template.divImgButton(
				(member == MadeBy.MEMBER_1 ? CommonResources.INSTANCE.addIconMember1()
						: member == MadeBy.MEMBER_2 ? CommonResources.INSTANCE.addIconMember2()
								: CommonResources.INSTANCE.addIcon()).getSafeUri(), CommonResources.INSTANCE.style()
						.button(), SafeHtmlUtils.fromString(memberName));
	}

	@Override
	public List<SharedExpense> elementList() {
		return this.listDataProvider.getList();
	}

	@UiHandler("btnCancel")
	void onCancelButtonClicked(ClickEvent evt) {
		this.hideModificationForm();
	}

	@UiHandler("btnOk")
	void onOkButtonClicked(ClickEvent evt) {
		this.saveModificationForm();
	}

	@UiHandler("btnDelete")
	void onDeleteButtonToggled(ValueChangeEvent<Boolean> evt) {
		boolean enabled = Boolean.TRUE.equals(evt.getValue());
		this.setActionMode(enabled ? ActionMode.DELETE_ELEMENT : ActionMode.MODIFY_ELEMENT);

		if (enabled) {
			// btnCalendar.setValue(false, true);
		}
	}

	@UiHandler("btnCleanBill")
	void onCleanBillButtonClicked(ClickEvent evt) {
		this.presenter.onCleanBill();
	}

	@Override
	public void setLoading(boolean loading) {
		this.loading = loading;
		btnDelete.setEnabled(!loading);
	}

	@Override
	public boolean isLoading() {
		return this.loading;
	}

	@Override
	public void setActionMode(ActionMode mode) {
		this.actionMode = mode;
		switch (mode) {
		case DELETE_ELEMENT:
			this.lstElements.setSelectionModel(multiSelectionModel);
			btnDelete.setDown(true);
			boardManager.setValue(Board.MAIN_LIST);
			addSelectionColumn(multiSelectionModel);
			break;
		case MODIFY_ELEMENT:
			this.lstElements.setSelectionModel(singleSelectionModel);
			btnDelete.setDown(false);
			removeSelectionColumn();
			break;
		}

		this.presenter.onActionModeChanged();
	}

	@Override
	public ActionMode getActionMode() {
		return actionMode;
	}

	@Override
	public Set<SharedExpense> getSelection() {
		return ((SetSelectionModel<SharedExpense>) this.lstElements.getSelectionModel()).getSelectedSet();
	}

	@Override
	public boolean isEnabled() {
		return this.enabled;
	}

	@Override
	public void setEnabled(boolean enabled) {
		this.enabled = true;
		HasEnabledWrapper.setEnabled(enabled, btnDelete);
		this.setTitle(enabled ? "" : "¡Asociate a tu pareja antes de empezar a usar todas las opciones!");
	}

	@Override
	public HasValue<Date> formDate() {
		return HasValueWrapper.from(date, true, this);
	}

	@Override
	public void saveModificationForm() {
		this.presenter.onElementModified();
	}

	@Override
	public void showModifyForm(SharedExpense element) {
		this.modifyingElement = element;
		if (element.getMadeBy() == null) {
			this.formMember.setText("miembro");
		} else {
			switch (element.getMadeBy()) {
			case MEMBER_1:
				this.formMember.setText(member1Name().getValue());
				break;
			case MEMBER_2:
				this.formMember.setText(member2Name().getValue());
				break;
			}
		}
		this.date.setValue(element.getDate());
		this.description.setValue(element.getText());
		this.amount.setValue(element.getAmount());
		this.boardManager.setValue(Board.EDIT_FORM);
		this.shared.setValue(element.isShared(), true);
		nonSharedInfo.setVisible(!element.isShared());
		Scheduler.get().scheduleDeferred(new ScheduledCommand() {

			@Override
			public void execute() {
				description.getElement().focus();
			}
		});
		// this.formDialog.center();
	}

	@UiHandler("shared")
	void onSharedCheckboxValueChanged(ValueChangeEvent<Boolean> evt) {
		nonSharedInfo.setVisible(Boolean.FALSE.equals(evt.getValue()));
	}

	@Override
	public void hideModificationForm() {
		// this.formDialog.hide();
		this.boardManager.setValue(Board.MAIN_LIST);
	}

	@Override
	public HasValue<String> member1Name() {
		return HasValueAdapter.<String> forField("member1Name", this).onChange(new OnChangeCommand<String>() {

			@Override
			public void execute(String name) {
				member1Header.setHtml(getMemberHeaderSafeHtml(name, MadeBy.MEMBER_1));
				requiresHeaderRedraw();
			}
		});
	}

	@Override
	public HasValue<String> member2Name() {
		return HasValueAdapter.<String> forField("member2Name", this).onChange(new OnChangeCommand<String>() {

			@Override
			public void execute(String name) {
				member2Header.setHtml(getMemberHeaderSafeHtml(name, MadeBy.MEMBER_2));
				requiresHeaderRedraw();
			}
		});
	}

	protected void requiresHeaderRedraw() {
		if (!this.pendingHeaderRedraw) {
			this.pendingHeaderRedraw = true;
			Scheduler.get().scheduleFinally(new ScheduledCommand() {

				@Override
				public void execute() {
					pendingHeaderRedraw = false;
					lstElements.redrawHeaders();
				}
			});
		}

	}

	@Override
	public SharedExpense modifyingElement() {
		return this.modifyingElement;
	}

	@Override
	public HasValue<String> formText() {
		return this.description;
	}

	@Override
	public HasValue<Boolean> formShared() {
		return HasValueWrapper.from(this.shared, true, this);
	}

	@Override
	public HasValue<BigDecimal> formAmount() {
		return this.amount;
	}

	@Override
	public boolean checkformValidity() {
		return form.checkValidity();
	}

	@Override
	public HasValue<BigDecimal> totalMember1() {
		return this.totalMember1;
	}

	@Override
	public HasValue<BigDecimal> totalMember2() {
		return this.totalMember2;
	}

	@Override
	public void setDebtsStatus(DebtsStatus value, BigDecimal amount) {
		String member1Name = member1Name().getValue();
		String member2Name = member2Name().getValue();
		if (value != null) {
			if (member1Name == null || member2Name == null) {
				logger.info("Cannot show debts status. Names are null: name1={0}, name2={1}", member1Name, member2Name);
			} else {
				switch (value) {
				case CLEAN:
					result.setHTML(template.div(common.style().commonText(), "La cuenta está igualada."));
					break;
				case MEMBER1_OWES:
					result.setHTML(sharedExpensesTemplate.owes(common.style().member1(), member1Name, style.amount()
							+ ' ' + common.style().commonText(), NumberFormat.getCurrencyFormat().format(amount),
							common.style().member2(), member2Name));
					break;
				case MEMBER2_OWES:
					result.setHTML(sharedExpensesTemplate.owes(common.style().member2(), member2Name, style.amount()
							+ ' ' + common.style().commonText(), NumberFormat.getCurrencyFormat().format(amount),
							common.style().member1(), member1Name));
					break;
				case SINGLE:
					result.setHTML("");
					break;
				}
			}
		} else {
			result.setHTML("");
		}
	}

	private void addSelectionColumn(SetSelectionModel<SharedExpense> sm) {
		if (this.checkColumn == null) {
			this.checkColumn = CheckColumn.insertCheckColumn(sm, lstElements, 0, "");
			this.lstElements.setColumnWidth(checkColumn, 20, Unit.PX);

			this.lstElements.getHeader(0).setHeaderStyleNames(style.selector());

			this.checkColumn.setCellStyleNames(style.selector());
		}

	}

	private void removeSelectionColumn() {
		if (this.checkColumn != null) {
			this.lstElements.removeColumn(checkColumn);
			this.checkColumn = null;
		}

	}

	@Override
	public void clearSelection() {
		this.singleSelectionModel.clear();
		this.multiSelectionModel.clear();
	}

	@Override
	public HasValue<Board> boardShown() {
		return this.boardManager;
	}

	@Override
	public boolean goBoardBack() {
		return this.presenter.onGoBoardBack();
	}

	@Override
	public void scrollToElement(final int idx) {
		Scheduler.get().scheduleDeferred(new ScheduledCommand() {

			@Override
			public void execute() {
				TableRowElement rowElement = lstElements.getRowElement(idx);
				if (rowElement != null) {
					rowElement.scrollIntoView();
				}
			}
		});
	}

	@Override
	public HasValue<Boolean> total1IncludeNotShared() {
		return HasValueAdapter.<Boolean> forField("total1IncludeNotShared", this).onChange(
				new OnChangeCommand<Boolean>() {

					@Override
					public void execute(Boolean value) {
						totalMember1.setStyleName(style.nonShared(), Boolean.TRUE.equals(value));
					}
				});
	}

	@Override
	public HasValue<Boolean> total2IncludeNotShared() {
		return HasValueAdapter.<Boolean> forField("total2IncludeNotShared", this).onChange(
				new OnChangeCommand<Boolean>() {

					@Override
					public void execute(Boolean value) {
						totalMember2.setStyleName(style.nonShared(), Boolean.TRUE.equals(value));
					}
				});
	}

	@Override
	public HasEnabled notSharedActionEnabled() {
		return HasEnabledWrapper.from(this.shared, this);
	}

	@Override
	public HasVisibility member1ActionsVisible() {
		return HasVisibilityAdapter.forField("member1ActionsVisible", this).onChange(new OnChangeCommand<Boolean>() {

			@Override
			public void execute(Boolean value) {
				initColumns();
			}
		});
	}

	@Override
	public HasVisibility member2ActionsVisible() {
		return HasVisibilityAdapter.forField("member2ActionsVisible", this).onChange(new OnChangeCommand<Boolean>() {

			@Override
			public void execute(Boolean value) {
				initColumns();
			}
		});
	}
}
